package com.avic.modules.realtime.service;

import com.avic.modules.equipment.service.EquipmentCategoryService;
import com.avic.modules.equipment.service.dto.EquipmentQueryCriteria;
import com.avic.modules.realtime.enums.NettyEnum;
import com.avic.modules.realtime.event.TaskEvent;
import com.avic.utils.RedisUtils;
import com.google.common.eventbus.EventBus;
import io.netty.util.HashedWheelTimer;
import io.netty.util.concurrent.DefaultThreadFactory;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @author ayetony.miao
 * @date 2022/8/19 16:08
 **/
@Service
@Slf4j
public class PushThreadService {


    private final EventBus eventBus;
    private final EquipmentCategoryService equipmentCategoryService;
    private final RedisUtils redisUtils;


    public PushThreadService(EventBus eventBus, EquipmentCategoryService equipmentCategoryService, RedisUtils redisUtils) {
        this.eventBus = eventBus;
        this.equipmentCategoryService = equipmentCategoryService;
        this.redisUtils = redisUtils;
        ScheduledThreadPoolExecutor service = (ScheduledThreadPoolExecutor) Executors.newScheduledThreadPool(1);
        service.setExecuteExistingDelayedTasksAfterShutdownPolicy(false);
        service.scheduleAtFixedRate(this::runCyclingPush, 3000, 5000, TimeUnit.MILLISECONDS);
    }

    /**
     * 构建HashedWheelTimer时间轮
     * <p>
     * threadFactory：创建处理任务的线程工厂
     * tickDuration：100 ，表示每个时间格代表当前时间轮的基本时间跨度，这里是100ms，也就是指针100ms跳动一次，每次跳动一个窗格
     * ticksPerWheel：512，表示时间轮上一共有多少个时间格，分配的时间格越多，占用内存空间就越大
     * leakDetection：是否开启内存泄漏检测
     * maxPendingTimeouts[可选参数]，最大允许等待的任务数，默认没有限制
     * <p>
     * 最后通过newTimeout()把需要延迟执行的任务添加到时间轮中
     */
    private static final HashedWheelTimer HASHED_WHEEL_TIMER = new HashedWheelTimer(
            new DefaultThreadFactory("hashed-timer"),
            100,
            TimeUnit.MILLISECONDS,
            64,
            true);

    public void runCyclingPush() {
        long delay = 5000;
        HASHED_WHEEL_TIMER.newTimeout(timeout -> kanban(), delay, TimeUnit.MILLISECONDS);

    }

    public void kanban() {
        try {
            Map<String,Object> stringObjectHashMap = equipmentCategoryService.queryStation(new EquipmentQueryCriteria());
            TaskEvent taskEvent = new TaskEvent();
            taskEvent.setMessage(NettyEnum.PUSH_MESSAGE_TASK.getMessage());
            taskEvent.setData(stringObjectHashMap);
            eventBus.post(taskEvent);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }


}
